<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
		"http://www.w3.org/TR/html4/strict.dtd">

<!--
	Tests the old dijit/_base/popup API.
	Remove in 2.0.   Replaced by dijit/tests/popup.html.
-->

<html>
<head>
	<title>Dijit.popup and BackgroundIFrame unit test</title>
	<style type="text/css">
		@import "../../themes/claro/document.css";
		@import "../../themes/dijit.css";
		@import "../css/dijitTests.css";

		body {
			height: 100%;
			padding: 0;
			margin: 0;
		}

		div {
			background: white;
			border: solid 1px gray;
		}

		/* the menu type test widgets */
		.choice div {
			width: 200px;
			cursor: pointer;
		}
		.choice div:hover {
			background: #ccc;
		}
	</style>
	<script type="text/javascript" src="../../../dojo/dojo.js"
		data-dojo-config="isDebug: true, parseOnLoad: false"></script>
	<script type="text/javascript" src="../_testCommon.js"></script>

	<script type="text/javascript">
		dojo.require("doh.runner");
		dojo.require("dijit._base.popup");
		dojo.require("dijit._Widget");
		dojo.require("dijit._TemplatedMixin");
		dojo.require("dijit.tests.helpers");	// functions to help test

		function log(str){
			console.log(str);
		}

		dojo.ready(function(){

			dojo.declare("SimpleDropDownButton", [dijit._Widget, dijit._TemplatedMixin], {
				// summary:
				//		A button that shows a popup.
				//		Supply popup as parameter when instantiating this widget.

				label: "show popup",
				orient: {'BL': 'TL', 'BR': 'TR'},

				templateString: "<button data-dojo-attach-event='onclick: openPopup'>${label}</button>",

				openPopup: function(){
					var self = this;

					dijit.popup.open({
						popup: this.popup,
						parent: this,
						around: this.domNode,
						orient: this.orient,
						onCancel: function(){
							log(self.id + ": cancel of child");
						},
						onExecute: function(){
							log(self.id + ": execute of child");
							dijit.popup.close(self.popup);
							self.open = false;
						}
					});

					this.open = true;
				},

				closePopup: function(){
					if(this.open){
						log(this.id + ": close popup due to blur");
						dijit.popup.close(this.popup);
						this.open = false;
					}
				},

				_onBlur: function(){
					// summary:
					//		This is called from focus manager and when we get the signal we
					//		need to close the drop down
					this.closePopup();
				}
			});

			dojo.declare("SimplePopup",  [dijit._Widget, dijit._TemplatedMixin], {
				// summary:
				//		A trivial popup widget

				templateString: "<span>i'm a popup</span>"
			});

			dojo.declare("SimpleChoiceWidget",  [dijit._Widget, dijit._TemplatedMixin], {
				// summary:
				//		A list of values; select a value by pressing an entry in the list.

				choice1: "1",
				choice2: "2",
				choice3: "3",

				templateString:
					"<div class='choice'>" +
						"<div data-dojo-attach-event='onclick: onClick'>${choice1}</div>" +
						"<div data-dojo-attach-event='onclick: onClick'>${choice2}</div>" +
						"<div data-dojo-attach-event='onclick: onClick'>${choice3}</div>" +
					"</div>",

				onClick: function(e){
					this.onChange(e.target.innerHTML);
				},

				onChange: function(val){
					// summary:
					//		When this widget is used as a popup, dijit.popup monitors calls
					//		to onChange and then closes the popup
					log(this.id + ": selected " + val);
				}
			});

			// Create a button that displays a simple drop down
			choiceDropDown = new SimpleChoiceWidget();
			(choiceDropDownButton = new SimpleDropDownButton({
				id: "choiceDropDownButton",
				label: "show choice drop down",
				popup: choiceDropDown
			})).placeAt(dojo.byId("widgets"));

			dojo.declare("DialogWithPopupWidget",  [dijit._Widget, dijit._TemplatedMixin], {
				// summary:
				//		This is a dialog that contains a button that spawns a drop down.
				//		Supply popup as an argument to this widget.

				title: "I'm a dialog",
				label: "click me",

				templateString:
					"<div style='width: 300px'>" +
						"<div>${title}</div>" +
						"<input><br>" +
						"<button data-dojo-attach-point='button'>${label}</button><br>" +
						"<button data-dojo-attach-event='onclick: onExecute'>OK</button>" +
					"</div>",

				postCreate: function(){
					// Convert the plain button into a SimpleDropDownButton widget.
					// Having it be a widget is important because that's how the popup
					// code knows where a stack of nested popups (typically menus) ends.
					// (In this case closing a stack of menus shouldn't close the dialog.)

					new SimpleDropDownButton({
						id: this.id + "PopupButton",
						label: this.label,
						popup: this.popup,
						orient: {'BR': 'BL', 'TR': 'tL'}	// so popup doesn't cover OK button
					}, this.button);
				},

				onExecute: function(){
					// summary:
					//		Called when OK button is pressed.
					//		If this is used as a popup this signals to the parent that
					//		Dialog can be closed.
					console.log(this.id + ": executed");
				}
			});

			// Create a button that displays a dialog that displays a choice widget
			dialogDropDownButton = new SimpleDropDownButton({
				id: "showSimpleDialogButton",
				label: "show dialog",
				popup: new DialogWithPopupWidget({
					id: "simpleDialog",
					label: 'show simple choice drop down',
					popup: new SimpleChoiceWidget({
						id: "choiceFromDialog"
					})
				})
			}).placeAt(dojo.byId("widgets"));

			dojo.declare("NestedPopupOpener",  [dijit._Widget, dijit._TemplatedMixin], {
				// summary:
				//		Clicking a value in this list will open a nested popup.
				//		Specify popup1 and popup2 as parameters to this widget.

				templateString:
					"<div class='choice'>" +
						"<div data-dojo-attach-event='onclick: onClick'>popup1</div>" +
						"<div data-dojo-attach-event='onclick: onClick'>popup2</div>" +
					"</div>",

				onClick: function(e){
					var id = this.id,
						popup = this[e.target.innerHTML];
					log(id + ": opening popup " + popup.id);
					this.openPopup(popup);
				},

				openPopup: function(popup){
					dijit.popup.open({
						popup: popup,
						parent: this,
						around: this.domNode,
						orient: {'TR': 'TL', 'TL': 'TR'},
						onCancel: function(){
							log(id + ": cancel of child " + popup.id);
						},
						onExecute: function(){
							log(id + ": execute of child " + popup.id);
							dijit.popup.close(popup);
						}
					})
				},

				closePopup: function(popup){
					dijit.popup.close(popup);
				}
			});

			// Create a button that displays a nested drop down.
			nestedOpener = new NestedPopupOpener({
				id: 'nestedPopupOpener',
				popup1: (nestedChoice1 = new SimpleChoiceWidget({
					id: "nestedChoice1"
				})),
				popup2: (nestedChoice2 = new SimpleChoiceWidget({
					id: "nestedChoice2",
					choice1: "4",
					choice2: "5",
					choice3: "6"
				}))
			});
			nestedDropDownButton = new SimpleDropDownButton({
				id: "showNestedMenuButton",
				label: "show nested drop down",
				popup: nestedOpener
			}).placeAt(dojo.byId("widgets"));

			// Create a button that displays a dialog that displays a nested drop down
			dialogNestedChoice1 = new SimpleChoiceWidget({
				id: "dialogNestedChoice1"
			});
			dialogNestedChoice2 = new SimpleChoiceWidget({
				id: "dialogNestedChoice2",
				choice1: "4",
				choice2: "5",
				choice3: "6"
			});
			dialogNestedPopupOpener = new NestedPopupOpener({
				id: "nestedPopupOpenerFromDialog",
				popup1: dialogNestedChoice1,
				popup2: dialogNestedChoice2
			});
			dialogWithNestedPopup = new DialogWithPopupWidget({
				id: "buttonInComplexDialog",
				label: 'show nested menu',
				popup: dialogNestedPopupOpener
			});
			dialogDropDownButton = new SimpleDropDownButton({
				id: "showComplexDialogButton",
				label: "show dialog w/nested menu",
				popup: dialogWithNestedPopup
			}).placeAt(dojo.byId("widgets"));

			// For testing, create an unattached widget and unattached DOMNode
			new SimplePopup({id: "spw"}).placeAt(dojo.body());
			dojo.place("<span id='sdn'>simple dom node</span>", dojo.body());

			doh.register("API", [
					function repeatMoveOffScreen(){
						// Previously, calling moveOffScreen twice would cause an exception
						dijit.popup.moveOffScreen(dijit.byId("spw"));
						dijit.popup.moveOffScreen(dijit.byId("spw"));

						// Deprecated API where moveOffScreen() takes a DOMNode
						dijit.popup.moveOffScreen(dojo.byId("sdn"));
						dijit.popup.moveOffScreen(dojo.byId("sdn"));
					}
			]);

			doh.register("simple open and close", [
				function initialConditions(t){
					// If the popup code has cached any iframes, make sure they are hidden
					dojo.query("iframe").forEach(function(node){
						console.log("found iframe", node);
						doh.is("none", node.style.display, "background iframe is hidden");
					});
				},

				// Create popup on the edge of another widget
				function openAround(){
					var d = new doh.Deferred();

					var around = dojo.global.choiceDropDownButton,
						popup = dojo.global.choiceDropDown;

					around.openPopup();

					setTimeout(d.getTestCallback(function(){
						doh.t(isVisible(popup.domNode), "popup is visible");

						if(dojo.isIE <= 6){
							// Test the BackgroundIFrame
							var iframes = dojo.query("iframe");
							doh.is(1, iframes.length, "one background iframe on IE6");

							var popupCoords = dojo.position(popup.domNode),
								iframeCoords = dojo.position(iframes[0]);
							doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
							doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
							doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
							doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
							doh.is("", iframes[0].style.display, "not display:none");
						}
						// TODO: test stack
					}), 500);

					return d;
				},

				function closeAround(){
					// Close the popup
					var around = dojo.global.choiceDropDownButton,
						popup = dojo.global.choiceDropDown;

					around.closePopup();

					// Make sure the popup is hidden
					doh.is("none", popup.domNode.parentNode.style.display, "popup is hidden");
				}
			]);

			doh.register("nested open and close", [
				// Open first level
				function openAround(){
					var d = new doh.Deferred();

					var around = dojo.global.nestedDropDownButton,
						popup = dojo.global.nestedOpener,
						nestedPopup = dojo.global.nestedChoice1;

					around.openPopup();

					setTimeout(d.getTestCallback(function(){
						doh.t(isVisible(popup.domNode), "popup is visible");

						if(dojo.isIE <= 6){
							// Test the BackgroundIFrame
							var iframes = dojo.query("iframe", popup.domNode.parentNode);
							doh.is(1, iframes.length, "one background iframe on IE6");

							var popupCoords = dojo.position(popup.domNode),
								iframeCoords = dojo.position(iframes[0]);
							doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
							doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
							doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
							doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
							doh.is("", iframes[0].style.display, "not display:none");
						}
						// TODO: test stack
					}), 500);

					return d;
				},

				function openNested(){
					var d = new doh.Deferred();

					var around = dojo.global.nestedDropDownButton,
						popup = dojo.global.nestedOpener,
						nestedPopup = dojo.global.nestedChoice1;

					popup.openPopup(nestedPopup);

					setTimeout(d.getTestCallback(function(){
						doh.t(isVisible(nestedPopup.domNode), "nested popup is visible");

						if(dojo.isIE <= 6){
							// Test the BackgroundIFrame
							var iframes = dojo.query("iframe", popup.domNode.parentNode);
							doh.is(1, iframes.length, "one background iframe for popup");

							iframes = dojo.query("iframe", nestedPopup.domNode.parentNode);
							doh.is(1, iframes.length, "another background iframe for nested popup");

							var popupCoords = dojo.position(nestedPopup.domNode),
								iframeCoords = dojo.position(iframes[0]);
							doh.is(popupCoords.x, iframeCoords.x, "x is same: " + popupCoords.x);
							doh.is(popupCoords.y, iframeCoords.y, "y is same: " + popupCoords.y);
							doh.is(popupCoords.w, iframeCoords.w, "w is same: " + popupCoords.w);
							doh.is(popupCoords.h, iframeCoords.h, "h is same: " + popupCoords.h);
							doh.is("", iframes[0].style.display, "not display:none");
						}
						// TODO: test stack
					}), 500);

					return d;
				},

				function closeAround(){
					// Close the layer of popups
					var around = dojo.global.nestedDropDownButton,
						popup = dojo.global.nestedOpener,
						nestedPopup = dojo.global.nestedChoice1;

					around.closePopup();

					// Make sure the popups are both hidden
					// (in a future release this might change to display:none etc but currently it's visibility:hidden)
					doh.is("none", popup.domNode.parentNode.style.display, "popup is hidden");
					doh.is("none", nestedPopup.domNode.parentNode.style.display, "nested popup is hidden");
				}
			]);

			// Make sure there are no hidden tab stops when popups are closed.
			// This test doesn't work on safari (due to safari bugs) although there aren't any hidden tab stops.
			doh.register("no hidden tab stops", function hiddenTabStops(){
				var tabbable = tabOrder();
				doh.is("inputAtStart", tabbable[0].id, "first tabbable node");
				doh.is("inputAtEnd", tabbable[tabbable.length - 1].id, "last tabbable node");
			});

			// TODO: test x/y placement

			// Test that onCancel goes back one level.
			// Call nestedChoice2.onCancel() and that should trigger nestedChoice2 to close
			// but nestedOpener stays open.
			// (TODO)

			// Test that onChange/onExecute goes back to top of popup chain.
			// Call dialogNestedChoice2.onChange() and that should trigger dialogNestedChoice2
			// and dialogNestedPopupOpener to close, but not dialogWithNestedPopup.
			// (TODO)

			// ---------------------
			// a11y tests

			// Test that ESC key closes one level of a popup chain.
			// Focus nestedChoice2 and type ESC, and that should trigger nestedChoice2 to close
			// but nestedOpener stays open.
			// (TODO)

			// Test that TAB key cancels back to top of popup chain.
			// Focus nestedChoice2 and type TAB, and that should trigger dialogNestedChoice2
			// and dialogNestedPopupOpener to close, but not dialogWithNestedPopup.
			// (TODO)

			doh.run();
		});
	</script>
</head>
<body>
	<h1>dijit.popup and BackgroundIFrame Unit Test</h1>
	<input id="inputAtStart">
	<span id="widgets"></span>
	<input id="inputAtEnd">
</body>
</html>
